#include "gtkbutton.h"
#include "gtkcelllayout.h"
#include "gtkcomboboxprivate.h"
+#include "gtkfilterlistmodel.h"
+#include "gtkflattenlistmodel.h"
+#include "gtkiconprivate.h"
#include "gtkiconview.h"
#include "gtklabel.h"
+#include "gtklistbox.h"
#include "gtkmenuitem.h"
#include "gtksettings.h"
+#include "gtksizegroup.h"
#include "gtktextview.h"
+#include "gtktogglebutton.h"
+#include "gtktreelistmodel.h"
#include "gtktreeview.h"
#include "gtktreeselection.h"
#include "gtktreestore.h"
#include "gtksearchbar.h"
#include "gtksearchentry.h"
#include "gtkeventcontrollerkey.h"
-#include "treewalk.h"
enum
{
struct _GtkInspectorObjectTreePrivate
{
- GtkTreeView *tree;
- GtkTreeStore *model;
- gulong map_hook;
- gulong unmap_hook;
- GtkTreeViewColumn *object_column;
+ GtkListBox *list;
+ GtkTreeListModel *tree_model;
GtkWidget *search_bar;
GtkWidget *search_entry;
- GtkTreeWalk *walk;
- gint search_length;
+ GtkSizeGroup *type_size_group;
+ GtkSizeGroup *name_size_group;
+ GtkSizeGroup *label_size_group;
};
typedef struct _ObjectTreeClassFuncs ObjectTreeClassFuncs;
struct _ObjectTreeClassFuncs {
GType (* get_type) (void);
GObject * (* get_parent) (GObject *object);
- void (* forall) (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data);
- gboolean (* get_sensitive) (GObject *object);
+ GListModel * (* get_children) (GObject *object);
};
static guint signals[LAST_SIGNAL] = { 0 };
return g_object_get_data (object, "inspector-object-tree-parent");
}
-static void
-object_tree_forall_default (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data)
+static GListModel *
+object_tree_get_children_default (GObject *object)
{
-}
-
-static gboolean
-object_tree_get_sensitive_default (GObject *object)
-{
- return TRUE;
+ return NULL;
}
static GObject *
return w ? G_OBJECT (w) : NULL;
}
-static gboolean
-object_tree_widget_get_sensitive (GObject *object)
+static GListModel *
+object_tree_widget_get_children (GObject *object)
{
- return gtk_widget_get_mapped (GTK_WIDGET (object));
-}
+ GtkWidget *widget = GTK_WIDGET (object);
+ GtkFlattenListModel *flatten;
+ GListStore *list;
+ GListModel *sublist;
-typedef struct {
- ObjectTreeForallFunc forall_func;
- gpointer forall_data;
-} ForallData;
+ list = g_list_store_new (G_TYPE_LIST_MODEL);
-static void
-object_tree_widget_forall (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data)
+ sublist = gtk_widget_observe_children (widget);
+ g_list_store_append (list, sublist);
+ g_object_unref (sublist);
+
+ sublist = gtk_widget_observe_controllers (widget);
+ g_list_store_append (list, sublist);
+ g_object_unref (sublist);
+
+ flatten = gtk_flatten_list_model_new (G_TYPE_OBJECT, G_LIST_MODEL (list));
+ g_object_unref (list);
+
+ return G_LIST_MODEL (flatten);
+}
+
+static GListModel *
+object_tree_tree_model_sort_get_children (GObject *object)
{
- struct {
- GtkPropagationPhase phase;
- const gchar *name;
- } phases[] = {
- { GTK_PHASE_CAPTURE, "capture" },
- { GTK_PHASE_TARGET, "target" },
- { GTK_PHASE_BUBBLE, "bubble" },
- { GTK_PHASE_NONE, "" }
- };
- gint i;
- GtkWidget *child;
-
- for (i = 0; i < G_N_ELEMENTS (phases); i++)
- {
- GList *list, *l;
+ GListStore *store;
- list = _gtk_widget_list_controllers (GTK_WIDGET (object), phases[i].phase);
- for (l = list; l; l = l->next)
- {
- GObject *controller = l->data;
- forall_func (controller, phases[i].name, forall_data);
- }
- g_list_free (list);
- }
+ store = g_list_store_new (G_TYPE_OBJECT);
+ g_list_store_append (store, gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (object)));
- if (gtk_widget_is_toplevel (GTK_WIDGET (object)))
- {
- GObject *clock;
-
- clock = G_OBJECT (gtk_widget_get_frame_clock (GTK_WIDGET (object)));
- if (clock)
- forall_func (clock, "frame-clock", forall_data);
- }
-
- for (child = gtk_widget_get_first_child (GTK_WIDGET (object));
- child != NULL;
- child = gtk_widget_get_next_sibling (child))
- {
- forall_func (G_OBJECT (child), NULL, forall_data);
- }
+ return G_LIST_MODEL (store);
}
-static void
-object_tree_tree_model_sort_forall (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data)
+static GListModel *
+object_tree_tree_model_filter_get_children (GObject *object)
{
- GObject *child = G_OBJECT (gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (object)));
+ GListStore *store;
- if (child)
- forall_func (child, "model", forall_data);
+ store = g_list_store_new (G_TYPE_OBJECT);
+ g_list_store_append (store, gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (object)));
+
+ return G_LIST_MODEL (store);
}
static void
-object_tree_tree_model_filter_forall (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data)
+update_list_store (GListStore *store,
+ GObject *object,
+ const char *property)
{
- GObject *child = G_OBJECT (gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (object)));
+ gpointer value;
- if (child)
- forall_func (child, "model", forall_data);
+ g_object_get (object, property, &value, NULL);
+ if (value)
+ {
+ g_list_store_splice (store,
+ 0,
+ g_list_model_get_n_items (G_LIST_MODEL (store)),
+ &value,
+ 1);
+ g_object_unref (value);
+ }
+ else
+ {
+ g_list_store_remove_all (store);
+ }
}
static void
-object_tree_menu_item_forall (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data)
+list_model_for_property_notify_cb (GObject *object,
+ GParamSpec *pspec,
+ GListStore *store)
{
- GtkWidget *submenu;
+ update_list_store (store, object, pspec->name);
+}
+
+static GListModel *
+list_model_for_property (GObject *object,
+ const char *property)
+{
+ GListStore *store = g_list_store_new (G_TYPE_OBJECT);
- submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (object));
- if (submenu)
- forall_func (G_OBJECT (submenu), "submenu", forall_data);
+ /* g_signal_connect_object ("notify::property") */
+ g_signal_connect_closure_by_id (object,
+ g_signal_lookup ("notify", G_OBJECT_TYPE (object)),
+ g_quark_from_static_string (property),
+ g_cclosure_new_object (G_CALLBACK (list_model_for_property_notify_cb), G_OBJECT (store)),
+ FALSE);
+ update_list_store (store, object, property);
+
+ return G_LIST_MODEL (store);
}
-static void
-object_tree_combo_box_forall (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data)
+static GListModel *
+list_model_for_properties (GObject *object,
+ const char **props)
{
- GtkWidget *popup;
- GObject *child;
+ GListStore *concat;
+ GListModel *result;
+ guint i;
- popup = gtk_combo_box_get_popup (GTK_COMBO_BOX (object));
- if (popup)
- forall_func (G_OBJECT (popup), "popup", forall_data);
+ if (props[1] == NULL)
+ return list_model_for_property (object, props[0]);
- child = G_OBJECT (gtk_combo_box_get_model (GTK_COMBO_BOX (object)));
- if (child)
- forall_func (child, "model", forall_data);
+ concat = g_list_store_new (G_TYPE_LIST_MODEL);
+ for (i = 0; props[i]; i++)
+ {
+ GListModel *tmp = list_model_for_property (object, props[i]);
+ g_list_store_append (concat, tmp);
+ g_object_unref (tmp);
+ }
+
+ result = G_LIST_MODEL (gtk_flatten_list_model_new (G_TYPE_OBJECT, G_LIST_MODEL (concat)));
+ g_object_unref (concat);
+ return result;
}
-static void
-object_tree_tree_view_forall (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data)
+static GListModel *
+object_tree_menu_item_get_children (GObject *object)
+{
+ return list_model_for_properties (object, (const char *[2]) { "submenu", NULL });
+}
+
+static GListModel *
+object_tree_combo_box_get_children (GObject *object)
{
- gint n_columns, i;
- GObject *child;
+ return list_model_for_properties (object, (const char *[2]) { "model", NULL });
+}
- child = G_OBJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (object)));
- if (child)
- forall_func (child, "model", forall_data);
+static void
+treeview_columns_changed (GtkTreeView *treeview,
+ GListModel *store)
+{
+ GtkTreeViewColumn *column, *item;
+ guint i, n_columns, n_items;
- child = G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (object)));
- if (child)
- forall_func (child, "selection", forall_data);
+ n_columns = gtk_tree_view_get_n_columns (treeview);
+ n_items = g_list_model_get_n_items (store);
- n_columns = gtk_tree_view_get_n_columns (GTK_TREE_VIEW (object));
- for (i = 0; i < n_columns; i++)
+ for (i = 0; i < MAX (n_columns, n_items); i++)
{
- child = G_OBJECT (gtk_tree_view_get_column (GTK_TREE_VIEW (object), i));
- forall_func (child, NULL, forall_data);
+ column = gtk_tree_view_get_column (treeview, i);
+ item = g_list_model_get_item (store, i);
+ g_object_unref (item);
+
+ if (column == item)
+ continue;
+
+ if (n_columns < n_items)
+ {
+ /* column removed */
+ g_assert (n_columns + 1 == n_items);
+ g_list_store_remove (G_LIST_STORE (store), i);
+ return;
+ }
+ else if (n_columns > n_items)
+ {
+ /* column added */
+ g_assert (n_columns - 1 == n_items);
+ g_list_store_insert (G_LIST_STORE (store), i, column);
+ return;
+ }
+ else
+ {
+ guint j;
+ /* column reordered */
+ for (j = n_columns - 1; j > i; j--)
+ {
+ column = gtk_tree_view_get_column (treeview, j);
+ item = g_list_model_get_item (store, j);
+ g_object_unref (item);
+
+ if (column != item)
+ break;
+ }
+ g_assert (j > i);
+ column = gtk_tree_view_get_column (treeview, i);
+ item = g_list_model_get_item (store, j);
+ g_object_unref (item);
+
+ if (item == column)
+ {
+ /* column was removed from position j and put into position i */
+ g_list_store_remove (G_LIST_STORE (store), j);
+ g_list_store_insert (G_LIST_STORE (store), i, column);
+ }
+ else
+ {
+ /* column was removed from position i and put into position j */
+ column = gtk_tree_view_get_column (treeview, j);
+ g_list_store_remove (G_LIST_STORE (store), i);
+ g_list_store_insert (G_LIST_STORE (store), j, column);
+ }
+ }
}
}
-static void
-object_tree_icon_view_forall (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data)
+static GListModel *
+object_tree_tree_view_get_children (GObject *object)
{
- GObject *child;
+ GtkTreeView *treeview = GTK_TREE_VIEW (object);
+ GListStore *columns, *selection, *result_list;
+ GListModel *props;
+ GtkFlattenListModel *result;
+ guint i;
- child = G_OBJECT (gtk_icon_view_get_model (GTK_ICON_VIEW (object)));
- if (child)
- forall_func (child, "model", forall_data);
+ props = list_model_for_properties (object, (const char *[2]) { "model", NULL });
+
+ columns = g_list_store_new (GTK_TYPE_TREE_VIEW_COLUMN);
+ g_signal_connect_object (treeview, "columns-changed", G_CALLBACK (treeview_columns_changed), columns, 0);
+ for (i = 0; i < gtk_tree_view_get_n_columns (treeview); i++)
+ g_list_store_append (columns, gtk_tree_view_get_column (treeview, i));
+
+ selection = g_list_store_new (GTK_TYPE_TREE_SELECTION);
+ g_list_store_append (selection, gtk_tree_view_get_selection (treeview));
+
+ result_list = g_list_store_new (G_TYPE_LIST_MODEL);
+ g_list_store_append (result_list, props);
+ g_object_unref (props);
+ g_list_store_append (result_list, selection);
+ g_object_unref (selection);
+ g_list_store_append (result_list, columns);
+ g_object_unref (columns);
+ result = gtk_flatten_list_model_new (G_TYPE_OBJECT, G_LIST_MODEL (result_list));
+ g_object_unref (result_list);
+
+ return G_LIST_MODEL (result);
}
-typedef struct {
- ObjectTreeForallFunc forall_func;
- gpointer forall_data;
- GObject *parent;
-} ParentForallData;
+static GListModel *
+object_tree_icon_view_get_children (GObject *object)
+{
+ return list_model_for_properties (object, (const char *[2]) { "model", NULL });
+}
static gboolean
-cell_callback (GtkCellRenderer *renderer,
- gpointer data)
+object_tree_cell_area_add_child (GtkCellRenderer *renderer,
+ gpointer store)
{
- ParentForallData *d = data;
gpointer cell_layout;
- cell_layout = g_object_get_data (d->parent, "gtk-inspector-cell-layout");
+ cell_layout = g_object_get_data (store, "gtk-inspector-cell-layout");
g_object_set_data (G_OBJECT (renderer), "gtk-inspector-cell-layout", cell_layout);
- d->forall_func (G_OBJECT (renderer), NULL, d->forall_data);
+
+ g_list_store_append (store, renderer);
return FALSE;
}
-static void
-object_tree_cell_area_forall (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data)
+static GListModel *
+object_tree_cell_area_get_children (GObject *object)
{
- ParentForallData data = {
- forall_func,
- forall_data,
- object
- };
+ GListStore *store;
+ gpointer cell_layout;
+
+ cell_layout = g_object_get_data (object, "gtk-inspector-cell-layout");
+ store = g_list_store_new (GTK_TYPE_CELL_RENDERER);
+ g_object_set_data (G_OBJECT (store), "gtk-inspector-cell-layout", cell_layout);
+ /* XXX: no change notification for cell areas */
+ gtk_cell_area_foreach (GTK_CELL_AREA (object), object_tree_cell_area_add_child, store);
- gtk_cell_area_foreach (GTK_CELL_AREA (object), cell_callback, &data);
+ return G_LIST_MODEL (store);
}
-static void
-object_tree_cell_layout_forall (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data)
+static GListModel *
+object_tree_cell_layout_get_children (GObject *object)
{
+ GListStore *store;
GtkCellArea *area;
/* cell areas handle their own stuff */
if (GTK_IS_CELL_AREA (object))
- return;
+ return NULL;
area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (object));
if (!area)
- return;
+ return NULL;
g_object_set_data (G_OBJECT (area), "gtk-inspector-cell-layout", object);
- forall_func (G_OBJECT (area), "cell-area", forall_data);
+ /* XXX: are cell areas immutable? */
+ store = g_list_store_new (G_TYPE_OBJECT);
+ g_list_store_append (store, area);
+ return G_LIST_MODEL (store);
}
-static void
-object_tree_text_view_forall (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data)
+static GListModel *
+object_tree_text_view_get_children (GObject *object)
{
- GtkTextBuffer *buffer;
+ return list_model_for_properties (object, (const char *[2]) { "buffer", NULL });
+}
- buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (object));
- forall_func (G_OBJECT (buffer), "buffer", forall_data);
+static GListModel *
+object_tree_text_buffer_get_children (GObject *object)
+{
+ return list_model_for_properties (object, (const char *[2]) { "tag-table", NULL });
}
static void
-object_tree_text_buffer_forall (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data)
+text_tag_added (GtkTextTagTable *table,
+ GtkTextTag *tag,
+ GListStore *store)
{
- GtkTextTagTable *tags;
-
- tags = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (object));
- forall_func (G_OBJECT (tags), "tag-table", forall_data);
+ g_list_store_append (store, tag);
}
static void
-tag_callback (GtkTextTag *tag,
- gpointer data)
+text_tag_removed (GtkTextTagTable *table,
+ GtkTextTag *tag,
+ GListStore *store)
{
- ForallData *d = data;
- gchar *name;
+ guint i;
+
+ for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (store)); i++)
+ {
+ gpointer item = g_list_model_get_item (G_LIST_MODEL (store), i);
+ g_object_unref (item);
- g_object_get (tag, "name", &name, NULL);
- d->forall_func (G_OBJECT (tag), name, d->forall_data);
- g_free (name);
+ if (tag == item)
+ {
+ g_list_store_remove (store, i);
+ return;
+ }
+ }
}
static void
-object_tree_text_tag_table_forall (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data)
+text_tag_foreach (GtkTextTag *tag,
+ gpointer store)
{
- ForallData data = {
- forall_func,
- forall_data
- };
-
- gtk_text_tag_table_foreach (GTK_TEXT_TAG_TABLE (object), tag_callback, &data);
+ g_list_store_append (store, tag);
}
-static void
-object_tree_application_forall (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data)
+static GListModel *
+object_tree_text_tag_table_get_children (GObject *object)
{
- GObject *menu;
+ GListStore *store = g_list_store_new (GTK_TYPE_TEXT_TAG);
+
+ g_signal_connect_object (object, "tag-added", G_CALLBACK (text_tag_added), store, 0);
+ g_signal_connect_object (object, "tag-removed", G_CALLBACK (text_tag_removed), store, 0);
+ gtk_text_tag_table_foreach (GTK_TEXT_TAG_TABLE (object), text_tag_foreach, store);
+
+ return NULL;
+}
- menu = (GObject *)gtk_application_get_app_menu (GTK_APPLICATION (object));
- if (menu)
- forall_func (menu, "app-menu", forall_data);
+static GListModel *
+object_tree_application_get_children (GObject *object)
+{
+ return list_model_for_properties (object, (const char *[3]) { "app-menu", "menubar", NULL });
+}
- menu = (GObject *)gtk_application_get_menubar (GTK_APPLICATION (object));
- if (menu)
- forall_func (menu, "menubar", forall_data);
+static GObject *
+object_tree_event_controller_get_parent (GObject *object)
+{
+ return G_OBJECT (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (object)));
}
/* Note:
{
gtk_application_get_type,
object_tree_get_parent_default,
- object_tree_application_forall,
- object_tree_get_sensitive_default
+ object_tree_application_get_children
},
{
gtk_text_tag_table_get_type,
object_tree_get_parent_default,
- object_tree_text_tag_table_forall,
- object_tree_get_sensitive_default
+ object_tree_text_tag_table_get_children
},
{
gtk_text_buffer_get_type,
object_tree_get_parent_default,
- object_tree_text_buffer_forall,
- object_tree_get_sensitive_default
+ object_tree_text_buffer_get_children
},
{
gtk_text_view_get_type,
object_tree_widget_get_parent,
- object_tree_text_view_forall,
- object_tree_widget_get_sensitive
+ object_tree_text_view_get_children
},
{
gtk_icon_view_get_type,
object_tree_widget_get_parent,
- object_tree_icon_view_forall,
- object_tree_widget_get_sensitive
+ object_tree_icon_view_get_children
},
{
gtk_tree_view_get_type,
object_tree_widget_get_parent,
- object_tree_tree_view_forall,
- object_tree_widget_get_sensitive
+ object_tree_tree_view_get_children
},
{
gtk_combo_box_get_type,
object_tree_widget_get_parent,
- object_tree_combo_box_forall,
- object_tree_widget_get_sensitive
+ object_tree_combo_box_get_children
},
{
gtk_menu_item_get_type,
object_tree_widget_get_parent,
- object_tree_menu_item_forall,
- object_tree_widget_get_sensitive
+ object_tree_menu_item_get_children
},
{
gtk_menu_get_type,
object_tree_menu_get_parent,
- object_tree_widget_forall,
- object_tree_widget_get_sensitive
+ object_tree_widget_get_children
},
{
gtk_widget_get_type,
object_tree_widget_get_parent,
- object_tree_widget_forall,
- object_tree_widget_get_sensitive
+ object_tree_widget_get_children
},
{
gtk_tree_model_filter_get_type,
object_tree_get_parent_default,
- object_tree_tree_model_filter_forall,
- object_tree_get_sensitive_default
+ object_tree_tree_model_filter_get_children
},
{
gtk_tree_model_sort_get_type,
object_tree_get_parent_default,
- object_tree_tree_model_sort_forall,
- object_tree_get_sensitive_default
+ object_tree_tree_model_sort_get_children
},
{
gtk_cell_area_get_type,
object_tree_get_parent_default,
- object_tree_cell_area_forall,
- object_tree_get_sensitive_default
+ object_tree_cell_area_get_children
},
{
gtk_cell_layout_get_type,
object_tree_get_parent_default,
- object_tree_cell_layout_forall,
- object_tree_get_sensitive_default
+ object_tree_cell_layout_get_children
+ },
+ {
+ gtk_event_controller_get_type,
+ object_tree_event_controller_get_parent,
+ object_tree_get_children_default
},
{
g_object_get_type,
object_tree_get_parent_default,
- object_tree_forall_default,
- object_tree_get_sensitive_default
+ object_tree_get_children_default
},
};
return funcs->get_parent (object);
}
-static void
-object_forall (GObject *object,
- ObjectTreeForallFunc forall_func,
- gpointer forall_data)
+static GListModel *
+object_get_children (GObject *object)
{
GType object_type;
+ GListModel *result, *children;
+ GListStore *result_list;
guint i;
object_type = G_OBJECT_TYPE (object);
+ result = NULL;
+ result_list = NULL;
for (i = 0; i < G_N_ELEMENTS (object_tree_class_funcs); i++)
{
- if (g_type_is_a (object_type, object_tree_class_funcs[i].get_type ()))
- object_tree_class_funcs[i].forall (object, forall_func, forall_data);
- }
-}
+ if (!g_type_is_a (object_type, object_tree_class_funcs[i].get_type ()))
+ continue;
-static gboolean
-object_get_sensitive (GObject *object)
-{
- const ObjectTreeClassFuncs *funcs;
+ children = object_tree_class_funcs[i].get_children (object);
+ if (children == NULL)
+ continue;
- funcs = find_class_funcs (object);
-
- return funcs->get_sensitive (object);
-}
-
-static void
-on_row_activated (GtkTreeView *tree,
- GtkTreePath *path,
- GtkTreeViewColumn *col,
- GtkInspectorObjectTree *wt)
-{
- GtkTreeIter iter;
- GObject *object;
- gchar *name;
-
- gtk_tree_model_get_iter (GTK_TREE_MODEL (wt->priv->model), &iter, path);
- gtk_tree_model_get (GTK_TREE_MODEL (wt->priv->model), &iter,
- OBJECT, &object,
- OBJECT_NAME, &name,
- -1);
+ if (result_list)
+ {
+ g_list_store_append (result_list, children);
+ g_object_unref (children);
+ }
+ else if (result == NULL)
+ {
+ result = children;
+ }
+ else
+ {
+ result_list = g_list_store_new (G_TYPE_LIST_MODEL);
+ g_list_store_append (result_list, result);
+ g_object_unref (result);
+ g_list_store_append (result_list, children);
+ g_object_unref (children);
+ }
+ }
- g_signal_emit (wt, signals[OBJECT_ACTIVATED], 0, object, name);
+ if (result_list)
+ {
+ result = G_LIST_MODEL (gtk_flatten_list_model_new (G_TYPE_OBJECT, G_LIST_MODEL (result_list)));
+ g_object_unref (result_list);
+ }
- g_free (name);
+ return result;
}
-GObject *
-gtk_inspector_object_tree_get_selected (GtkInspectorObjectTree *wt)
+static const char *
+gtk_inspector_get_object_name (GObject *object)
{
- GObject *object;
- GtkTreeIter iter;
- GtkTreeSelection *sel;
- GtkTreeModel *model;
+ if (GTK_IS_WIDGET (object))
+ {
+ const gchar *id;
- object = NULL;
- sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (wt->priv->tree));
- if (gtk_tree_selection_get_selected (sel, &model, &iter))
- gtk_tree_model_get (model, &iter,
- OBJECT, &object,
- -1);
+ id = gtk_widget_get_name (GTK_WIDGET (object));
+ if (id != NULL && g_strcmp0 (id, G_OBJECT_TYPE_NAME (object)) != 0)
+ return id;
+ }
- return object;
-}
+ if (GTK_IS_BUILDABLE (object))
+ {
+ const gchar *id;
-static void
-on_selection_changed (GtkTreeSelection *selection,
- GtkInspectorObjectTree *wt)
-{
- GObject *object;
- GtkTreeIter iter;
+ id = gtk_buildable_get_name (GTK_BUILDABLE (object));
+ if (id != NULL && !g_str_has_prefix (id, "___object_"))
+ return id;
+ }
- if (gtk_tree_selection_get_selected (selection, NULL, &iter))
- gtk_tree_walk_reset (wt->priv->walk, &iter);
- else
- gtk_tree_walk_reset (wt->priv->walk, NULL);
- object = gtk_inspector_object_tree_get_selected (wt);
- g_signal_emit (wt, signals[OBJECT_SELECTED], 0, object);
+ return NULL;
}
-typedef struct {
- GObject *dead_object;
- GtkTreeWalk *walk;
- GtkTreePath *walk_pos;
-} RemoveData;
-
-static gboolean
-remove_cb (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
+char *
+gtk_inspector_get_object_title (GObject *object)
{
- RemoveData *remove_data = data;
- GObject *lookup;
-
- gtk_tree_model_get (model, iter, OBJECT, &lookup, -1);
+ const char *name = gtk_inspector_get_object_name (object);
- if (lookup == remove_data->dead_object)
- {
- if (remove_data->walk_pos != NULL &&
- gtk_tree_path_compare (path, remove_data->walk_pos) == 0)
- gtk_tree_walk_reset (remove_data->walk, NULL);
-
- gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
-
- return TRUE;
- }
-
- return FALSE;
+ if (name == NULL)
+ return g_strdup (G_OBJECT_TYPE_NAME (object));
+ else
+ return g_strconcat (G_OBJECT_TYPE_NAME (object), " — ", name, NULL);
}
static void
-gtk_object_tree_remove_dead_object (gpointer data, GObject *dead_object)
+on_row_activated (GtkListBox *box,
+ GtkListBoxRow *row,
+ GtkInspectorObjectTree *wt)
{
- GtkInspectorObjectTree *wt = data;
- GtkTreeIter iter;
- RemoveData remove_data;
-
- remove_data.dead_object = dead_object;
- remove_data.walk = wt->priv->walk;
- if (gtk_tree_walk_get_position (wt->priv->walk, &iter))
- remove_data.walk_pos = gtk_tree_model_get_path (GTK_TREE_MODEL (wt->priv->model), &iter);
- else
- remove_data.walk_pos = NULL;
+ guint pos;
+ GtkTreeListRow *item;
+ GObject *object;
+
+ pos = gtk_list_box_row_get_index (row);
+ item = g_list_model_get_item (G_LIST_MODEL (wt->priv->tree_model), pos);
+ object = gtk_tree_list_row_get_item (item);
- gtk_tree_model_foreach (GTK_TREE_MODEL (wt->priv->model), remove_cb, &remove_data);
+ g_signal_emit (wt, signals[OBJECT_ACTIVATED], 0, object);
- if (remove_data.walk_pos)
- gtk_tree_path_free (remove_data.walk_pos);
+ g_object_unref (item);
+ g_object_unref (object);
}
-static gboolean
-weak_unref_cb (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
+GObject *
+gtk_inspector_object_tree_get_selected (GtkInspectorObjectTree *wt)
{
- GtkInspectorObjectTree *wt = data;
+ GtkListBoxRow *selected_row;
+ guint selected_pos;
+ GtkTreeListRow *selected_row_item;
GObject *object;
- gtk_tree_model_get (model, iter, OBJECT, &object, -1);
+ selected_row = gtk_list_box_get_selected_row (wt->priv->list);
+ if (selected_row == NULL)
+ return NULL;
- g_object_weak_unref (object, gtk_object_tree_remove_dead_object, wt);
+ selected_pos = gtk_list_box_row_get_index (selected_row);
+ selected_row_item = g_list_model_get_item (G_LIST_MODEL (wt->priv->tree_model), selected_pos);
- return FALSE;
+ object = gtk_tree_list_row_get_item (selected_row_item);
+ g_object_unref (selected_row_item);
+
+ g_object_unref (object); /* ahem */
+ return object;
}
static void
-clear_store (GtkInspectorObjectTree *wt)
+widget_mapped (GtkWidget *widget,
+ GtkListBoxRow *row)
{
- if (wt->priv->model)
- {
- gtk_tree_model_foreach (GTK_TREE_MODEL (wt->priv->model), weak_unref_cb, wt);
- gtk_tree_store_clear (wt->priv->model);
- gtk_tree_walk_reset (wt->priv->walk, NULL);
- }
-}
+ GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET (row));
-static gboolean
-map_or_unmap (GSignalInvocationHint *ihint,
- guint n_params,
- const GValue *params,
- gpointer data)
-{
- GtkInspectorObjectTree *wt = data;
- GtkWidget *widget;
- GtkTreeIter iter;
-
- widget = g_value_get_object (params);
- if (gtk_inspector_object_tree_find_object (wt, G_OBJECT (widget), &iter))
- gtk_tree_store_set (wt->priv->model, &iter,
- SENSITIVE, gtk_widget_get_mapped (widget),
- -1);
- return TRUE;
+ gtk_style_context_remove_class (context, "dim-label");
}
static void
-move_search_to_row (GtkInspectorObjectTree *wt,
- GtkTreeIter *iter)
+widget_unmapped (GtkWidget *widget,
+ GtkListBoxRow *row)
{
- GtkTreeSelection *selection;
- GtkTreePath *path;
-
- selection = gtk_tree_view_get_selection (wt->priv->tree);
- path = gtk_tree_model_get_path (GTK_TREE_MODEL (wt->priv->model), iter);
- gtk_tree_view_expand_to_path (wt->priv->tree, path);
- gtk_tree_selection_select_path (selection, path);
- gtk_tree_view_scroll_to_cell (wt->priv->tree, path, NULL, TRUE, 0.5, 0.0);
- gtk_tree_path_free (path);
+ GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET (row));
+
+ gtk_style_context_add_class (context, "dim-label");
}
+static gboolean
+search (GtkInspectorObjectTree *wt,
+ gboolean forward,
+ gboolean force_progress);
+
static gboolean
key_pressed (GtkEventController *controller,
guint keyval,
keyval == GDK_KEY_ISO_Enter ||
keyval == GDK_KEY_KP_Enter))
{
- GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreeIter iter;
- GtkTreePath *path;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (wt->priv->tree));
- if (gtk_tree_selection_get_selected (selection, &model, &iter))
- {
- path = gtk_tree_model_get_path (model, &iter);
- gtk_tree_view_row_activated (GTK_TREE_VIEW (wt->priv->tree),
- path,
- wt->priv->object_column);
- gtk_tree_path_free (path);
-
- return GDK_EVENT_STOP;
- }
- else
- return GDK_EVENT_PROPAGATE;
+ gtk_widget_activate (GTK_WIDGET (wt->priv->list));
+ return GDK_EVENT_PROPAGATE;
}
else if (search_started &&
(keyval == GDK_KEY_Escape))
((state & (default_accel | GDK_SHIFT_MASK)) == (default_accel | GDK_SHIFT_MASK)) &&
(keyval == GDK_KEY_g || keyval == GDK_KEY_G))
{
- GtkTreeIter iter;
- if (gtk_tree_walk_next_match (wt->priv->walk, TRUE, TRUE, &iter))
- move_search_to_row (wt, &iter);
- else
+ if (!search (wt, TRUE, TRUE))
gtk_widget_error_bell (GTK_WIDGET (wt));
-
return GDK_EVENT_STOP;
}
else if (search_started &&
((state & (default_accel | GDK_SHIFT_MASK)) == default_accel) &&
(keyval == GDK_KEY_g || keyval == GDK_KEY_G))
{
- GtkTreeIter iter;
-
- if (gtk_tree_walk_next_match (wt->priv->walk, TRUE, FALSE, &iter))
- move_search_to_row (wt, &iter);
- else
+ if (!search (wt, TRUE, TRUE))
gtk_widget_error_bell (GTK_WIDGET (wt));
-
return GDK_EVENT_STOP;
}
}
toplevel);
}
-static void
-on_search_changed (GtkSearchEntry *entry,
- GtkInspectorObjectTree *wt)
-{
- GtkTreeIter iter;
- gint length;
- gboolean backwards;
-
- length = strlen (gtk_entry_get_text (GTK_ENTRY (entry)));
- backwards = length < wt->priv->search_length;
- wt->priv->search_length = length;
-
- if (length == 0)
- return;
-
- if (gtk_tree_walk_next_match (wt->priv->walk, backwards, backwards, &iter))
- move_search_to_row (wt, &iter);
- else if (!backwards)
- gtk_widget_error_bell (GTK_WIDGET (wt));
-}
-
static gboolean
match_string (const gchar *string,
const gchar *text)
}
static gboolean
-match_row (GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
+match_object (GObject *object,
+ const char *text)
{
- GtkInspectorObjectTree *wt = data;
- gchar *type, *name, *label;
- const gchar *text;
- gboolean match;
-
- text = gtk_entry_get_text (GTK_ENTRY (wt->priv->search_entry));
- gtk_tree_model_get (model, iter,
- OBJECT_TYPE, &type,
- OBJECT_NAME, &name,
- OBJECT_LABEL, &label,
- -1);
-
- match = (match_string (type, text) ||
- match_string (name, text) ||
- match_string (label, text));
-
- g_free (type);
- g_free (name);
- g_free (label);
+ if (match_string (G_OBJECT_TYPE_NAME (object), text) ||
+ match_string (gtk_inspector_get_object_name (object), text))
+ return TRUE;
- return match;
+ if (GTK_IS_LABEL (object))
+ return match_string (gtk_label_get_label (GTK_LABEL (object)), text);
+ else if (GTK_IS_BUTTON (object))
+ return match_string (gtk_button_get_label (GTK_BUTTON (object)), text);
+ else if (GTK_IS_WINDOW (object))
+ return match_string (gtk_window_get_title (GTK_WINDOW (object)), text);
+ else if (GTK_IS_TREE_VIEW_COLUMN (object))
+ return match_string (gtk_tree_view_column_get_title (GTK_TREE_VIEW_COLUMN (object)), text);
+ else
+ return FALSE;
}
-static void
-search_mode_changed (GObject *search_bar,
- GParamSpec *pspec,
- GtkInspectorObjectTree *wt)
+static GObject *
+search_children (GObject *object,
+ const char *text,
+ gboolean forward)
{
- if (!gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (search_bar)))
+ GListModel *children;
+ GObject *child, *result;
+ guint i, n;
+
+ children = object_get_children (object);
+ if (children == NULL)
+ return NULL;
+
+ n = g_list_model_get_n_items (children);
+ for (i = 0; i < n; i++)
{
- gtk_tree_walk_reset (wt->priv->walk, NULL);
- wt->priv->search_length = 0;
+ child = g_list_model_get_item (children, forward ? i : n - i - 1);
+ if (match_object (child, text))
+ return child;
+
+ result = search_children (child, text, forward);
+ g_object_unref (child);
+ if (result)
+ return result;
}
+
+ return NULL;
+}
+
+static gboolean
+search (GtkInspectorObjectTree *wt,
+ gboolean forward,
+ gboolean force_progress)
+{
+ GtkInspectorObjectTreePrivate *priv = wt->priv;
+ GListModel *model = G_LIST_MODEL (priv->tree_model);
+ GtkTreeListRow *row_item;
+ GObject *child, *result;
+ guint i, selected, n, row;
+ const char *text;
+
+ text = gtk_entry_get_text (GTK_ENTRY (priv->search_entry));
+ if (gtk_list_box_get_selected_row (priv->list))
+ {
+ selected = gtk_list_box_row_get_index (gtk_list_box_get_selected_row (priv->list));
+ }
+ else
+ {
+ selected = 0;
+ force_progress = FALSE;
+ }
+ n = g_list_model_get_n_items (model);
+
+ for (i = 0; i < n; i++)
+ {
+ row = (selected + (forward ? i : n - i - 1)) % n;
+ row_item = g_list_model_get_item (model, row);
+ child = gtk_tree_list_row_get_item (row_item);
+ if (i > 0 || !force_progress)
+ {
+ if (match_object (child, text))
+ {
+ gtk_list_box_select_row (priv->list, gtk_list_box_get_row_at_index (priv->list, row));
+ g_object_unref (child);
+ g_object_unref (row_item);
+ return TRUE;
+ }
+ }
+
+ if (!gtk_tree_list_row_get_expanded (row_item))
+ {
+ result = search_children (child, text, forward);
+ if (result)
+ {
+ g_print ("selecting!\n");
+ gtk_inspector_object_tree_select_object (wt, result);
+ g_object_unref (result);
+ g_object_unref (child);
+ g_object_unref (row_item);
+ return TRUE;
+ }
+ }
+ g_object_unref (child);
+ g_object_unref (row_item);
+ }
+
+ return FALSE;
+}
+
+static void
+on_search_changed (GtkSearchEntry *entry,
+ GtkInspectorObjectTree *wt)
+{
+ if (!search (wt, TRUE, FALSE))
+ gtk_widget_error_bell (GTK_WIDGET (wt));
}
static void
{
if (gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (wt->priv->search_bar)))
{
- GtkTreeIter iter;
-
- if (gtk_tree_walk_next_match (wt->priv->walk, TRUE, FALSE, &iter))
- move_search_to_row (wt, &iter);
- else
+ if (!search (wt, TRUE, TRUE))
gtk_widget_error_bell (GTK_WIDGET (wt));
}
}
{
if (gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (wt->priv->search_bar)))
{
- GtkTreeIter iter;
-
- if (gtk_tree_walk_next_match (wt->priv->walk, TRUE, TRUE, &iter))
- move_search_to_row (wt, &iter);
- else
+ if (!search (wt, FALSE, TRUE))
gtk_widget_error_bell (GTK_WIDGET (wt));
}
}
gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (wt->priv->search_bar), FALSE);
}
-static void
-gtk_inspector_object_tree_init (GtkInspectorObjectTree *wt)
+static GtkWidget *
+gtk_inspector_object_tree_create_list_widget (gpointer row_item,
+ gpointer user_data)
{
- guint signal_id;
+ GtkInspectorObjectTree *wt = user_data;
+ gpointer item;
+ GtkWidget *row, *box, *column, *child;
+ guint depth;
- wt->priv = gtk_inspector_object_tree_get_instance_private (wt);
- gtk_widget_init_template (GTK_WIDGET (wt));
+ item = gtk_tree_list_row_get_item (row_item);
- gtk_search_bar_connect_entry (GTK_SEARCH_BAR (wt->priv->search_bar),
- GTK_ENTRY (wt->priv->search_entry));
+ row = gtk_list_box_row_new ();
+ g_object_set_data_full (G_OBJECT (row), "make-sure-its-not-unreffed", g_object_ref (row_item), g_object_unref);
+ if (GTK_IS_WIDGET (item))
+ {
+ g_signal_connect_object (item, "map", G_CALLBACK (widget_mapped), row, 0);
+ g_signal_connect_object (item, "unmap", G_CALLBACK (widget_unmapped), row, 0);
+ if (!gtk_widget_get_mapped (item))
+ widget_unmapped (item, GTK_LIST_BOX_ROW (row));
+ }
+
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_container_add (GTK_CONTAINER (row), box);
+
+ column = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_size_group_add_widget (wt->priv->type_size_group, column);
+ gtk_container_add (GTK_CONTAINER (box), column);
+
+ /* expander */
+ depth = gtk_tree_list_row_get_depth (row_item);
+ if (depth > 0)
+ {
+ child = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_set_size_request (child, 16 * depth, 0);
+ gtk_container_add (GTK_CONTAINER (column), child);
+ }
+ if (gtk_tree_list_row_is_expandable (row_item))
+ {
+ GtkWidget *title, *arrow;
+
+ child = g_object_new (GTK_TYPE_BOX, "css-name", "expander", NULL);
+
+ title = g_object_new (GTK_TYPE_TOGGLE_BUTTON, "css-name", "title", NULL);
+ gtk_button_set_relief (GTK_BUTTON (title), GTK_RELIEF_NONE);
+ g_object_bind_property (row_item, "expanded", title, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+ gtk_container_add (GTK_CONTAINER (child), title);
+
+ arrow = gtk_icon_new ("arrow");
+ gtk_container_add (GTK_CONTAINER (title), arrow);
+ }
+ else
+ {
+ child = gtk_image_new (); /* empty whatever */
+ }
+ gtk_container_add (GTK_CONTAINER (column), child);
+
+ /* 1st column: type name */
+ child = gtk_label_new (G_OBJECT_TYPE_NAME (item));
+ gtk_label_set_width_chars (GTK_LABEL (child), 30);
+ gtk_label_set_xalign (GTK_LABEL (child), 0.0);
+ gtk_container_add (GTK_CONTAINER (column), child);
+
+ /* 2nd column: name */
+ child = gtk_label_new (gtk_inspector_get_object_name (item));
+ gtk_label_set_width_chars (GTK_LABEL (child), 15);
+ gtk_label_set_xalign (GTK_LABEL (child), 0.0);
+ gtk_size_group_add_widget (wt->priv->name_size_group, child);
+ gtk_container_add (GTK_CONTAINER (box), child);
+
+ /* 3rd column: label */
+ child = gtk_label_new (NULL);
+ if (GTK_IS_LABEL (item))
+ g_object_bind_property (item, "label", child, "label", G_BINDING_SYNC_CREATE);
+ else if (GTK_IS_BUTTON (item))
+ g_object_bind_property (item, "label", child, "label", G_BINDING_SYNC_CREATE);
+ else if (GTK_IS_WINDOW (item))
+ g_object_bind_property (item, "title", child, "label", G_BINDING_SYNC_CREATE);
+ else if (GTK_IS_TREE_VIEW_COLUMN (item))
+ g_object_bind_property (item, "title", child, "label", G_BINDING_SYNC_CREATE);
+ gtk_label_set_width_chars (GTK_LABEL (child), 15);
+ gtk_label_set_xalign (GTK_LABEL (child), 0.0);
+ gtk_size_group_add_widget (wt->priv->label_size_group, child);
+ gtk_container_add (GTK_CONTAINER (box), child);
+
+ g_object_unref (item);
+
+ return row;
+}
+
+static GListModel *
+create_model_for_object (gpointer object,
+ gpointer user_data)
+{
+ return object_get_children (object);
+}
+
+static gboolean
+toplevel_filter_func (gpointer item,
+ gpointer data)
+{
+ GdkDisplay *display = data;
- g_signal_connect (wt->priv->search_bar, "notify::search-mode-enabled",
- G_CALLBACK (search_mode_changed), wt);
- wt->priv->walk = gtk_tree_walk_new (GTK_TREE_MODEL (wt->priv->model), match_row, wt, NULL);
+ if (!GTK_IS_WINDOW (item))
+ return FALSE;
+
+ if (g_str_equal (G_OBJECT_TYPE_NAME (item), "GtkInspectorWindow"))
+ return FALSE;
- signal_id = g_signal_lookup ("map", GTK_TYPE_WIDGET);
- wt->priv->map_hook = g_signal_add_emission_hook (signal_id, 0,
- map_or_unmap, wt, NULL);
- signal_id = g_signal_lookup ("unmap", GTK_TYPE_WIDGET);
- wt->priv->unmap_hook = g_signal_add_emission_hook (signal_id, 0,
- map_or_unmap, wt, NULL);
+ return gtk_window_get_window_type (item) == GTK_WINDOW_TOPLEVEL &&
+ gtk_widget_get_display (item) == display;
+}
- gtk_inspector_object_tree_append_object (wt, G_OBJECT (gtk_settings_get_default ()), NULL, NULL);
+static GListModel *
+create_root_model (void)
+{
+ GtkFilterListModel *filter;
+ GtkFlattenListModel *flatten;
+ GListStore *list, *special;
+
+ list = g_list_store_new (G_TYPE_LIST_MODEL);
+
+ special = g_list_store_new (G_TYPE_OBJECT);
+ g_list_store_append (special, g_application_get_default ());
+ g_list_store_append (special, gtk_settings_get_default ());
+ g_list_store_append (list, special);
+ g_object_unref (special);
+
+ filter = gtk_filter_list_model_new_for_type (G_TYPE_OBJECT);
+ gtk_filter_list_model_set_filter_func (filter,
+ toplevel_filter_func,
+ g_object_ref (gdk_display_get_default ()),
+ g_object_unref);
+ gtk_filter_list_model_set_model (filter, gtk_window_get_toplevels ());
+ g_list_store_append (list, filter);
+ g_object_unref (filter);
+
+ flatten = gtk_flatten_list_model_new (G_TYPE_OBJECT, G_LIST_MODEL (list));
+ g_object_unref (list);
+ return G_LIST_MODEL (flatten);
}
static void
-gtk_inspector_object_tree_dispose (GObject *object)
+gtk_inspector_object_tree_init (GtkInspectorObjectTree *wt)
{
- GtkInspectorObjectTree *wt = GTK_INSPECTOR_OBJECT_TREE (object);
+ GListModel *root_model;
- clear_store (wt);
+ wt->priv = gtk_inspector_object_tree_get_instance_private (wt);
+ gtk_widget_init_template (GTK_WIDGET (wt));
- G_OBJECT_CLASS (gtk_inspector_object_tree_parent_class)->dispose (object);
+ gtk_search_bar_connect_entry (GTK_SEARCH_BAR (wt->priv->search_bar),
+ GTK_ENTRY (wt->priv->search_entry));
+
+ root_model = create_root_model ();
+ wt->priv->tree_model = gtk_tree_list_model_new (FALSE,
+ root_model,
+ FALSE,
+ create_model_for_object,
+ NULL,
+ NULL);
+ g_object_unref (root_model);
+
+ gtk_list_box_bind_model (wt->priv->list,
+ G_LIST_MODEL (wt->priv->tree_model),
+ gtk_inspector_object_tree_create_list_widget,
+ wt,
+ NULL);
}
static void
-gtk_inspector_object_tree_finalize (GObject *object)
+gtk_inspector_object_tree_dispose (GObject *object)
{
GtkInspectorObjectTree *wt = GTK_INSPECTOR_OBJECT_TREE (object);
- guint signal_id;
- signal_id = g_signal_lookup ("map", GTK_TYPE_WIDGET);
- g_signal_remove_emission_hook (signal_id, wt->priv->map_hook);
- signal_id = g_signal_lookup ("unmap", GTK_TYPE_WIDGET);
- g_signal_remove_emission_hook (signal_id, wt->priv->unmap_hook);
+ g_clear_object (&wt->priv->tree_model);
- gtk_tree_walk_free (wt->priv->walk);
-
- G_OBJECT_CLASS (gtk_inspector_object_tree_parent_class)->finalize (object);
+ G_OBJECT_CLASS (gtk_inspector_object_tree_parent_class)->dispose (object);
}
static void
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- object_class->finalize = gtk_inspector_object_tree_finalize;
object_class->dispose = gtk_inspector_object_tree_dispose;
signals[OBJECT_ACTIVATED] =
G_STRUCT_OFFSET (GtkInspectorObjectTreeClass, object_activated),
NULL, NULL,
NULL,
- G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_STRING);
+ G_TYPE_NONE, 1, G_TYPE_OBJECT);
signals[OBJECT_SELECTED] =
g_signal_new ("object-selected",
G_TYPE_NONE, 1, G_TYPE_OBJECT);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/object-tree.ui");
- gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorObjectTree, model);
- gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorObjectTree, tree);
- gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorObjectTree, object_column);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorObjectTree, list);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorObjectTree, search_bar);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorObjectTree, search_entry);
- gtk_widget_class_bind_template_callback (widget_class, on_selection_changed);
- gtk_widget_class_bind_template_callback (widget_class, on_row_activated);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorObjectTree, type_size_group);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorObjectTree, name_size_group);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorObjectTree, label_size_group);
gtk_widget_class_bind_template_callback (widget_class, on_hierarchy_changed);
gtk_widget_class_bind_template_callback (widget_class, on_search_changed);
+ gtk_widget_class_bind_template_callback (widget_class, on_row_activated);
gtk_widget_class_bind_template_callback (widget_class, next_match);
gtk_widget_class_bind_template_callback (widget_class, previous_match);
gtk_widget_class_bind_template_callback (widget_class, stop_search);
}
-typedef struct
-{
- GtkInspectorObjectTree *wt;
- GtkTreeIter *iter;
- GObject *parent;
-} FindAllData;
-
-static void
-child_callback (GObject *object,
- const char *name,
- gpointer data)
+static guint
+model_get_item_index (GListModel *model,
+ gpointer item)
{
- FindAllData *d = data;
-
- gtk_inspector_object_tree_append_object (d->wt, object, d->iter, NULL);
-}
-
-void
-gtk_inspector_object_tree_append_object (GtkInspectorObjectTree *wt,
- GObject *object,
- GtkTreeIter *parent_iter,
- const gchar *name)
-{
- GtkTreeIter iter;
- const gchar *class_name;
- gchar *classes;
- const gchar *label;
- FindAllData data;
-
- class_name = G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (object));
-
- if (GTK_IS_WIDGET (object))
- {
- const gchar *id;
- GtkStyleContext *context;
- GList *list, *l;
- GString *string;
-
- id = gtk_widget_get_name (GTK_WIDGET (object));
- if (name == NULL && id != NULL && g_strcmp0 (id, class_name) != 0)
- name = id;
+ gpointer cmp;
+ guint i;
- context = gtk_widget_get_style_context (GTK_WIDGET (object));
- string = g_string_new ("");
- list = gtk_style_context_list_classes (context);
- for (l = list; l; l = l->next)
- {
- if (string->len > 0)
- g_string_append_c (string, ' ');
- g_string_append (string, (gchar *)l->data);
- }
- classes = g_string_free (string, FALSE);
- g_list_free (list);
- }
- else
+ for (i = 0; (cmp = g_list_model_get_item (model, i)); i++)
{
- if (parent_iter)
+ if (cmp == item)
{
- GObject *parent;
-
- gtk_tree_model_get (GTK_TREE_MODEL (wt->priv->model), parent_iter,
- OBJECT, &parent,
- -1);
- g_object_set_data (object, "inspector-object-tree-parent", parent);
+ g_object_unref (cmp);
+ return i;
}
- classes = g_strdup ("");
+ g_object_unref (cmp);
}
- if (GTK_IS_BUILDABLE (object))
- {
- const gchar *id;
- id = gtk_buildable_get_name (GTK_BUILDABLE (object));
- if (name == NULL && id != NULL && !g_str_has_prefix (id, "___object_"))
- name = id;
- }
+ return G_MAXUINT;
+}
- if (name == NULL)
- name = "";
+static GtkTreeListRow *
+find_and_expand_object (GtkTreeListModel *model,
+ GObject *object)
+{
+ GtkTreeListRow *result;
+ GObject *parent;
+ guint pos;
- if (GTK_IS_LABEL (object))
- label = gtk_label_get_text (GTK_LABEL (object));
- else if (GTK_IS_BUTTON (object))
- label = gtk_button_get_label (GTK_BUTTON (object));
- else if (GTK_IS_WINDOW (object))
- label = gtk_window_get_title (GTK_WINDOW (object));
- else if (GTK_IS_TREE_VIEW_COLUMN (object))
- label = gtk_tree_view_column_get_title (GTK_TREE_VIEW_COLUMN (object));
- else
- label = "";
-
- gtk_tree_store_append (wt->priv->model, &iter, parent_iter);
- gtk_tree_store_set (wt->priv->model, &iter,
- OBJECT, object,
- OBJECT_TYPE, class_name,
- OBJECT_NAME, name,
- OBJECT_LABEL, label,
- OBJECT_CLASSES, classes,
- SENSITIVE, object_get_sensitive (object),
- -1);
-
- if (name && *name)
+ parent = object_get_parent (object);
+ if (parent)
{
- gchar *title;
- title = g_strconcat (class_name, " — ", name, NULL);
- g_object_set_data_full (object, "gtk-inspector-object-title", title, g_free);
+ GtkTreeListRow *parent_row = find_and_expand_object (model, parent);
+ if (parent_row == NULL)
+ return NULL;
+
+ gtk_tree_list_row_set_expanded (parent_row, TRUE);
+ pos = model_get_item_index (gtk_tree_list_row_get_children (parent_row), object);
+ result = gtk_tree_list_row_get_child (parent_row, pos);
+ g_object_unref (parent_row);
}
else
{
- g_object_set_data (object, "gtk-inspector-object-title", (gpointer)class_name);
+ pos = model_get_item_index (gtk_tree_list_model_get_model (model), object);
+ result = gtk_tree_list_model_get_child (model, pos);
}
-
- g_free (classes);
-
- g_object_weak_ref (object, gtk_object_tree_remove_dead_object, wt);
- data.wt = wt;
- data.iter = &iter;
- data.parent = object;
-
- object_forall (object, child_callback, &data);
-}
-
-static void
-block_selection_changed (GtkInspectorObjectTree *wt)
-{
- GtkTreeSelection *selection;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (wt->priv->tree));
- g_signal_handlers_block_by_func (selection, on_selection_changed, wt);
-}
-
-static void
-unblock_selection_changed (GtkInspectorObjectTree *wt)
-{
- GtkTreeSelection *selection;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (wt->priv->tree));
- g_signal_handlers_unblock_by_func (selection, on_selection_changed, wt);
-}
-
-static gboolean
-select_object_internal (GtkInspectorObjectTree *wt,
- GObject *object,
- gboolean activate)
-{
- GtkTreeIter iter;
-
- if (gtk_inspector_object_tree_find_object (wt, object, &iter))
- {
- GtkTreePath *path;
- GtkTreeSelection *selection;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (wt->priv->tree));
- path = gtk_tree_model_get_path (GTK_TREE_MODEL (wt->priv->model), &iter);
- gtk_tree_view_expand_to_path (GTK_TREE_VIEW (wt->priv->tree), path);
- if (!activate)
- block_selection_changed (wt);
- gtk_tree_selection_select_iter (selection, &iter);
- if (!activate)
- unblock_selection_changed (wt);
-
- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (wt->priv->tree), path, NULL, TRUE, 0.5, 0);
- if (activate)
- gtk_tree_view_row_activated (GTK_TREE_VIEW (wt->priv->tree), path, NULL);
- gtk_tree_path_free (path);
-
- return TRUE;
- }
-
- return FALSE;
+ return result;
}
-gboolean
+void
gtk_inspector_object_tree_select_object (GtkInspectorObjectTree *wt,
GObject *object)
{
- return select_object_internal (wt, object, TRUE);
-}
-
-void
-gtk_inspector_object_tree_scan (GtkInspectorObjectTree *wt,
- GtkWidget *window)
-{
- GtkWidget *inspector_win;
- GList *toplevels, *l;
- GdkDisplay *display;
- GObject *selected;
-
- block_selection_changed (wt);
-
- selected = gtk_inspector_object_tree_get_selected (wt);
-
- clear_store (wt);
- gtk_inspector_object_tree_append_object (wt, G_OBJECT (gtk_settings_get_default ()), NULL, NULL);
- if (g_application_get_default ())
- gtk_inspector_object_tree_append_object (wt, G_OBJECT (g_application_get_default ()), NULL, NULL);
-
- if (window)
- gtk_inspector_object_tree_append_object (wt, G_OBJECT (window), NULL, NULL);
-
- display = gdk_display_get_default ();
-
- inspector_win = gtk_widget_get_toplevel (GTK_WIDGET (wt));
- toplevels = gtk_window_list_toplevels ();
- for (l = toplevels; l; l = l->next)
- {
- if (GTK_IS_WINDOW (l->data) &&
- gtk_window_get_window_type (l->data) == GTK_WINDOW_TOPLEVEL &&
- gtk_widget_get_display (l->data) == display &&
- l->data != window &&
- l->data != inspector_win)
- gtk_inspector_object_tree_append_object (wt, G_OBJECT (l->data), NULL, NULL);
- }
- g_list_free (toplevels);
-
- gtk_tree_view_columns_autosize (GTK_TREE_VIEW (wt->priv->tree));
-
- if (selected)
- select_object_internal (wt, selected, FALSE);
-
- unblock_selection_changed (wt);
-}
-
-static gboolean
-gtk_inspector_object_tree_find_object_at_parent_iter (GtkTreeModel *model,
- GObject *object,
- GtkTreeIter *parent,
- GtkTreeIter *iter)
-{
- if (!gtk_tree_model_iter_children (model, iter, parent))
- return FALSE;
-
- do {
- GObject *lookup;
-
- gtk_tree_model_get (model, iter, OBJECT, &lookup, -1);
-
- if (lookup == object)
- return TRUE;
-
- } while (gtk_tree_model_iter_next (model, iter));
-
- return FALSE;
-}
-
-gboolean
-gtk_inspector_object_tree_find_object (GtkInspectorObjectTree *wt,
- GObject *object,
- GtkTreeIter *iter)
-{
- GtkTreeIter parent_iter;
- GObject *parent;
+ GtkTreeListRow *row_item;
+ GtkListBoxRow *row_widget;
- parent = object_get_parent (object);
- if (parent)
- {
- if (!gtk_inspector_object_tree_find_object (wt, parent, &parent_iter))
- return FALSE;
+ row_item = find_and_expand_object (wt->priv->tree_model, object);
+ if (row_item == NULL)
+ return;
- return gtk_inspector_object_tree_find_object_at_parent_iter (GTK_TREE_MODEL (wt->priv->model),
- object,
- &parent_iter,
- iter);
- }
- else
- {
- return gtk_inspector_object_tree_find_object_at_parent_iter (GTK_TREE_MODEL (wt->priv->model),
- object,
- NULL,
- iter);
- }
+ row_widget = gtk_list_box_get_row_at_index (wt->priv->list,
+ gtk_tree_list_row_get_position (row_item));
+ g_return_if_fail (row_widget != NULL);
+ gtk_list_box_select_row (wt->priv->list, row_widget);
+ g_object_unref (row_item);
}
-
-// vim: set et sw=2 ts=2: